#ifndef OD_H
#define OD_H

const static int MinPts = 20;

class OutlierDetection {
private:

	vector<vector<double>> centers_od;
	vector<vector<double>> points_od;
	vector<vector<double>> local_outlier;
	vector<int> key_pointID_pairVec;
	vector<vector<int>> pointID_pairVec;
	vector<vector<double>> pointID_dist;
	vector<int> local_outlier_pID;
	vector<int> pointsID_od;
	vector<int> sortPID_map_od;

	vector<double> outlier_center_dist;
	
	vector<string> cID_od;
	vector<string> local_outlier_status;
	vector<string> sortCID_map_od;
	vector<string> outlier_center_pair;
	vector<string> local_outlier_cluster;

public:
	OutlierDetection();
	~OutlierDetection();
	double DefineThreshold(double LO);
	void SetGlobalVariable(string t,vector<vector<double>> points,vector<int>pointsID);
	vector<vector<double>> FindMeanCluster(int CenterSize, int PointSize, int AttSize, vector<vector<int>> &pointEachCluster);
	vector<double> CalculatedLO(int AttSize, vector<vector<int>> pointEachCluster, vector<vector<double>> meanCluster);
	double EquationLO(double N, vector<vector<double>> meanCluster, vector<int> pointCluster, int AttSize, int i);
	void DetectLocalOutlier(vector<double> LO_Cluster, vector<vector<int>> pointEachCluster);
	void RemoveOutlierPoints(vector<vector<int>> pointEachCluster);
	void setupLOF(vector<vector<int>> pointEachCluster);
	double measureDist(vector<double> its_centers,vector<double> local_outlier_point);
	void collectMinPtsPointSameCluster(vector<vector<int>> ,vector<int> &nearMinPoint,vector<double> &nearMinPoint_dist);
	void collectMinPtsPointOtherCluster(vector<vector<int>> pointEachCluster, vector<int> &othernearMinPoint,vector<double> &othernearMinPoint_dist);
	void formMinPtsPointAllCluster(vector<int> nearMinPoint,vector<double> nearMinPoint_dist,vector<int> othernearMinPoint, vector<double> othernearMinPoint_dist,vector<vector<int>> &pID_vector,	vector<vector<double>> &dist_vector);
	void sortByValues(vector<int> &keys,vector<double> &values);
	void removeZeroValues(vector<int> &keys,vector<double> &values);
	void filterMinPts(vector<int> &keys,vector<double> &values);
	void findMinPtsOfQ(vector<vector<int>> pID_vector, vector<string> &current_q, vector<vector<int>> &current_q_NN, vector<vector<double>> &current_q_NN_dist);
	bool isPmember(int p, vector<int> q_NN);
	vector<double> defineReachDist(int choose, vector<string> current_q, vector<vector<int>> current_q_NN,vector<vector<double>> current_q_NN_dist);
	vector<double> CalculateIRD(vector<double> pq_distance,vector<string> current_q,vector<int> ird_n);
	vector<double> CalculateIRDsubQ(vector<double> pq_distance,vector<string> current_q,vector<int> ird_n, vector<vector<int>> pID_vector);
	vector<int> countN(vector<vector<int>> pID_vector);
	void findMinPtsOfsubQ(vector<string> current_q, vector<vector<int>> current_q_NN, vector<string> &current_sub_q, vector<vector<int>> &current_sub_q_NN, vector<vector<double>> &current_sub_q_NN_dist);
	vector<double> processIRDQ(vector<string> current_q,vector<vector<int>> current_q_NN,vector<vector<int>> pID_vector);
	vector<double> calculateLOF(vector<string> current_q,vector<double> ird_p,vector<double> ird_sub_p,vector<int> ird_n);
	vector<string> determineOutlierStatus(vector<double> lof_p);
	void returnUseValue(vector<int> &outlier_pointID,vector<string> &outlier_centerID);
	void readFileFormAllCluster(vector<vector<int>> &pID_vector,	vector<vector<double>> &dist_vector);
	void DefineKeyPoints(vector<vector<int>> current_q_NN);
	void readAllDistance();
	void calculateAllDistanceAllPoints(vector<int> points,vector<vector<double>>pointsID);
};
#endif
